#!/usr/bin/python3
# -*- coding: utf8 -*-
# Date   : 2021/06/27
# Author : Kwan
# Email  : allenxian@live.com
# Blog   : https://my.oschina.net/u/4173440

from math import ceil
from datetime import datetime
from project.flasky import db
from project.define import db_logger


DataName = "收费规则"
TableName = "app_parking_rule"


class CarParkRule(db.Model):
    """
    收费规则
    """
    __tablename__ = TableName
    # 规则ID
    RuleID = db.Column(db.Integer, primary_key=True, autoincrement=True, nullable=False)
    # 指定车型:Car,Moto
    VehicleType = db.Column(db.String(16), nullable=False)
    # 收费类型
    ParkingType = db.Column(db.String(16), nullable=False)
    # 时间范围
    TimeRange = db.Column(db.String(32))
    # 工作日:"1,2,3,4,5,6,7"
    WorkDays = db.Column(db.String(16))
    # 价格
    Price = db.Column(db.Float, nullable=False)

    def __init__(self, **kwargs) -> None:
        super().__init__()
        self.VehicleType = kwargs.get('VehicleType')
        self.ParkingType = kwargs.get('ParkingType')
        self.TimeRange = kwargs.get('TimeRange')
        self.WorkDays = self.__work_days_string(kwargs.get('WorkDays'))
        self.Price = kwargs.get('Price')

    def __work_days_string(self, val):
        """
        工作日
        """
        if isinstance(val, list):
            if len(val) == 1:
                return str(val[0])
            elif len(val) > 1:
                return ",".join(val)

    def to_dict(self):
        """
        转换键值对
        """
        def convert_data(name):
            val = getattr(self, name)
            if name == "WorkDays":
                if val:
                    if "," in val:
                        return val.split(",")
                    else:
                        return [val]
            return val
            
        return dict([(c.name, convert_data(c.name)) for c in self.__table__.columns])

    @staticmethod
    def selected_data(**kwargs):
        """
        选中数据
        """
        rule_id = kwargs.get('RuleID')
        if rule_id:
            return CarParkRule.query.filter_by(RuleID=rule_id).first()

    @staticmethod
    def columns_name():
        """
        数据表标题
        """
        ColumnName = {
            'RuleID':'規則ID','VehicleType':'車輛類型','ParkingType':'收費類型','TimeRange': '時間範圍', 'WorkDays': '工作日','Price':'收費標準'}
        return ColumnName

    @staticmethod
    def generate_filters(**kwargs):
        """
        筛选器
        """
        filters = set()
        for k, v in kwargs.items():
            if v:
                if hasattr(CarParkRule, k):
                    if k == 'VehicleType':
                        filters.add(CarParkRule.VehicleType == v)
                    elif k == 'ParkingType':
                        filters.add(CarParkRule.ParkingType == v)
                    elif k == 'TimeRange':
                        filters.add(CarParkRule.TimeRange == v)
                    elif k == 'Price':
                        filters.add(CarParkRule.Price == v)
                    elif k == 'WorkDays':
                        if isinstance(v, list):
                            if len(v) == 1:
                                v = v[0]
                            else:
                                v = ",".join(v)
                            filters.add(CarParkRule.WorkDays == v)
        return filters
    
    @staticmethod
    def check_exists(**kwargs):
        """
        规则是否存在
        """
        if "WorkDays" in kwargs:
            kwargs.pop("WorkDays")
        filters = CarParkRule.generate_filters(**kwargs)
        return CarParkRule.query.filter(*filters).first()

    @staticmethod
    def insert_data(**kwargs):
        """
        新增
        """
        try:
            r = CarParkRule(**kwargs)
            db.session.add(r)
            db.session.commit()
            db_logger.debug(f"{TableName} => 新增{DataName}成功：{kwargs}")
            return r.to_dict()
        except Exception as e:
            db.session.rollback()
            db_logger.error(f"{TableName} => 新增{DataName}失败：{kwargs} 原因：{e}")

    @staticmethod
    def delete_data(**kwargs):
        """
        删除
        """
        try:
            r = CarParkRule.selected_data(**kwargs)
            if r:
                db.session.delete(r)
                db.session.commit()
                db_logger.debug(f"{TableName} => 删除{DataName}成功：{kwargs}")
                return r.to_dict()
        except Exception as e:
            db.session.rollback()
            db_logger.error(f"{TableName} => 删除{DataName}失败：{kwargs} 原因：{e}")

    @staticmethod
    def modify_data(**kwargs):
        """
        修改车位
        """
        try:
            r = CarParkRule.selected_data(**kwargs)
            if r:
                for k, v in kwargs.items():
                    if hasattr(r, k):
                        if k == "WorkDays":
                            v = ",".join(v)
                        if getattr(r, k) != v:
                            setattr(r, k, v)
                            update = True
                if update:
                    try:
                        db.session.commit()
                        db_logger.debug(f"{TableName} => 更新{DataName}成功：{kwargs}")
                        return r.to_dict()
                    except Exception as e:
                        db.session.rollback()
                        db_logger.error(f"{TableName} => 更新{DataName}失败：{kwargs} 原因：{e}")
                        update = False
                else:
                    return "ignore"
            return update
        except Exception as e:
            db_logger.error(f"{TableName} => 更新{DataName}参数错误：{kwargs} 原因：{e}")
    
    @staticmethod
    def generate_hourly_parking_cost(**kwargs):
        """
        计算费用
        """
        parking_type = kwargs.get('ParkingType')
        vehicle_type = kwargs.get('VehicleType')
        pay_time = datetime.now()
        r = CarParkRule.query.filter(
            CarParkRule.VehicleType==vehicle_type,CarParkRule.ParkingType==parking_type,CarParkRule.WorkDays.like(f"%{pay_time.weekday()+1}%")
            ).first()
        if r:
            entrance_time = datetime.strptime(kwargs.get('EntranceTime'), "%Y/%m/%d %H:%M:%S")
            hours = ceil((pay_time - entrance_time).total_seconds() / 3600)
            cost = r.Price * hours
            return {'Money':cost,"ParkingTime": hours}

    @staticmethod
    def table_init():
        """
        初始化数据
        """
        demo_data = [
            {'VehicleType':'Car','ParkingType':'Hourly','TimeRange': '00:00:00 - 23:59:59', 'WorkDays': ['1','2','3','4','5','6','7'],'Price':6.0},
            {'VehicleType':'Moto','ParkingType':'Hourly','TimeRange': '00:00:00 - 23:59:59', 'WorkDays': ['1','2','3','4','5','6','7'],'Price':3.0},
            {'VehicleType':'Car','ParkingType':'Monthly','TimeRange': '', 'WorkDays': [],'Price':1000},
            {'VehicleType':'Moto','ParkingType':'Monthly','TimeRange': '', 'WorkDays': [],'Price':500},
        ]
        for i in demo_data:
            if not CarParkRule.check_exists(**i):
                CarParkRule.insert_data(**i)
